<?php

namespace app\service;

use app\exception\ModelEmptyException;
use app\exception\ModelException;
use app\model\Attachment;
use app\model\Category;
use app\model\CategorySubContent;
use app\model\Model;
use app\model\Module;
use app\model\ModuleField;
use app\model\RecycleBin;
use app\model\SubContent;
use app\model\SysSetting;
use app\model\WebsiteSetting;
use app\scaffold\Table;
use think\exception\ValidateException;
use think\facade\Db;

class ContentService {

    /**
     * @var \app\model\Content
     */
    public static $model = null;
    /**
     * @var array
     */
    public static $macro = [];

//    public $macro = [];

    public static $belongsTo = [];

    public static $hasMany = [];

    protected static $arrayField =  ['多图','多视频','多文件','日期时间区间','列表多选','多选'];

    /**
     * @var \app\scaffold\Table
     */
    protected $table;

    public function __construct()
    {
        $this->table = new Table();
    }

    public static function getTagContentDetail($id,$sellerId,$lang,$siteId)
    {
        try {
            $SubContent = new SubContent();
            $where = [
                ['id','=',$id],
                ['seller_id','=',$sellerId],
                ['publish_time','<',date('Y-m-d H:i:s',time())],
                ['status','=',1],
                ['is_del','=',1],
            ];
            $subContent = $SubContent->getSubContent($where,['category.module.moduleField'=>function($q)use($lang,$siteId,$sellerId){
                $q->where(['seller_id'=>$sellerId,'website_id'=>$siteId,'lang'=>$lang]);
            },'thumbnail'=>function($q){
                $q->field('id,name,url,type');
            },'cover'=>function($q){
                $q->field('id,name,url,type');
            }])['data'];
            $article = self::$model->where(['sub_id' => $id, 'seller_id' => $sellerId])->find();
            if(empty($article)){
                throw new ModelEmptyException();
            }
            $cate = $subContent['cate'];
            $article = '';
            if(!empty($cate)){
                $table = $cate['0']['module']['table'];
                self::setModel($table);
                $attachField = self::setSpecialField($cate['module']['moduleField']);
                self::getSpecialField($article,$attachField);
            }
            $subContent['main_content'] = $article;
        }catch (ModelEmptyException $me){
            throw new ModelEmptyException();
        } catch (\Exception $e){
            throw new ModelException();
        }
        return $subContent;
    }

    /**
     * 配置列表
     * @throws ModelException
     * @throws ModelEmptyException
     */
    public static function tagSetting($param)
    {
        if($param['type'] == 1){
            // 系统配置
            $SysSetting = new SysSetting();
            $setting = $SysSetting->getSysSetting(['seller_id'=>$param['sellerId'],'title'=>$param['name']])['data'];
            if(!empty($setting)){
                $setting = $setting['value'];
            }else{
                $setting = '';
            }
        }else{
            // 网站配置
            $WebsiteSetting = new WebsiteSetting();
            $setting = $WebsiteSetting->getWebsiteSetting(['seller_id'=>$param['sellerId'],'website_id'=>$param['siteId'],'lang'=>$param['lang']])['data']->toArray();
            if(!empty($setting)){
                $setting = json_decode($setting['setting'],true);
                if(!empty($setting[$param['name']])){
                    if( $param['name'] =="logo"){
                        $attachment = new Attachment();
                        $attach = $attachment->getAttachment(['id'=>$setting[$param['name']],'seller_id'=>$param['sellerId']])['data'];
                        if(!empty($attach)){
                            $setting = $attach['url'];
                        }else{
                            $setting = null;
                        }
                    }else{
                        $setting = $setting[$param['name']];

                    }
                }else{
                    $setting = '';
                }
            }else{
                $setting = '';
            }

        }
        return $setting;
    }

    /**
     * 分页标签数据
     */
    public static function tagContentPage($param)
    {
        $cid = (int)request()->param('id');
        $Category = new Category();
        $cate = $Category->getCategory(['id'=>$cid,'website_id'=>$param['siteId'],'lang'=>$param['lang']],['module.moduleField'])['data']->toArray();
        $path = $cate['path'].'-'.$cid;
        $cates = $Category->getCategoryList([['website_id','=',$param['siteId']],['lang','=',$param['lang']],['path','like','%'.$path]])['data']->toArray();
        if(empty($param['limit'])){
            $param['limit'] = null;
        }
        $cateIds = array_column($cates,'id');
        array_push($cateIds,$cid);
        if(!count($cateIds)){
            return [];
        }
        $table = $cate['module']['table'];
        $attachField = self::getAttachField($cate['module']['moduleField']);
        self::setModel($table);
        $cateSub = new CategorySubContent();
        if(count($cateIds) == 1){
            $where = [
                'category_id' => $cateIds[0],
                'seller_id' => $param['sellerId'],
            ];
        }else{
            $where = [
                ['category_id','in',$cateIds],
                ['seller_id','=',$param['sellerId']],
            ];
        }

        $cateSubCon = $cateSub->where($where)->select()->toArray();
        return self::tagContent($cateSubCon, $param, $attachField);
    }

    /**
     * 内容标签数据
     * @throws ModelEmptyException
     * @throws ModelException
     */
    public static function tagContentList($param)
    {
        if(empty($param['limit'])){
            $param['limit'] = null;
        }
        $cateIds = explode(',',$param['cid']);
        if(!count($cateIds)){
            return [];
        }
        $Category = new Category();
        $cates = $Category->getCategoryList([['id','in',$cateIds],['website_id','=' ,$param['siteId']]])['data']->toArray();
        $cateIdArr= array_column($cates,'id');
        $cateIds = array_intersect($cateIds,$cateIdArr);
        $module = self::getModule($param['module_id'],$param['sellerId']);
        $table = $module['table'];
        $attachField = self::getAttachField($module['moduleField']);
        self::setModel($table);
        $cateSub = new CategorySubContent();
        if(count($cateIds) == 1){
            $where = [
                'category_id' => $cateIds[0],
                'seller_id' => $param['sellerId'],
            ];
        }else{
            $where = [
                ['category_id','in',$cateIds],
                ['seller_id','=',$param['sellerId']],
            ];
        }
        $cateSubCon = $cateSub->where($where)->select()->toArray();
        return self::tagContent($cateSubCon, $param, $attachField);
    }

    /**
     *
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\db\exception\DbException
     */
    public static function tagContent($cateSubCon, $param, $attachField)
    {
        if(empty($cateSubCon)){
            if($param['asPage'] == 1 && $param['onlyData']==1){
                return  ['count' => 0, 'data' => []];
            }else{
                return  [];
            }
        }else{
            $where = self::setPageWhere($param);
            $subIds = array_column($cateSubCon,'sub_content_id');
            $mainField = explode(',',$param['mainField']);
            array_push($mainField,'seller_id');
            if(!empty($param['subField'])){
                $subField  = explode(',',$param['subField']);
            }else{
                $subField  = $param['subField'];
            }

            $SubContent = new SubContent();
            $content = $SubContent->field($mainField);

            $with = ['tag'=>function($q)use($param){
                $q->where(['website_id'=>$param['siteId'],'lang'=>$param['lang']]);
            }];
            if(in_array('thumbnail',$mainField)){
                $with = self::setMainImageWith('thumbnail',$with);
            }
            if(in_array('cover',$mainField)){
                $with = self::setMainImageWith('cover',$with);
            }
            if(!empty($with)){
                $content = $SubContent->field($mainField)->with($with);
            }
            $order = self::setOrder($param['sort']);
            $content = $content -> where($where)->whereIn('id',$subIds)->whereTime('publish_time','<=',time())->order($order);
            if($param['asPage'] == 1){
                $page = request()->param('page');
                if($page){
                    $param['page'] = $page;
                }
                $limit = request()->param('limit');
                if($limit){
                    $param['limit'] = $limit;
                }
                $query = request()->except(['id','cid','page','limit']);
                if(!empty($query)){
                    $content->where($query);
                }
                $content = $content->paginate([
                    'page' => $param['page'],
                    'list_rows' => $param['limit'],
                ]);
            }else{
                if(!empty($param['limit'])){
                    $content->limit((int)$param['limit']);
                }
                $content = $content->select();
            }
            $cateSubCon = getColumnForKeyArray($cateSubCon,'sub_content_id');
            $content->each(function(&$item)use($param,$attachField,$subField,$cateSubCon,$with){
                $item['category_id'] = $cateSubCon[$item['id']]['category_id'];
                if(!empty($subField)){
                    $mainContent = self::$model->where(['sub_id'=>$item['id'],'seller_id'=>$param['sellerId']])->find();
                    $mainContent = self::getMainContent($mainContent,$attachField);
                    $item['main_content'] = $mainContent;
                }
                if(isset($with['thumbnail'])){
                    $item['thumbnail'] = $item->toArray()['thumbnail'];
                }
                if(isset($with['cover'])){
                    $item['cover'] = $item->toArray()['cover'];
                }
            });
            if($param['asPage'] == 1){
                if($param['onlyData'] == 1){
                    return ['total'=>$content->total(),'data'=>$content->all()];
                }else{
                    return $content;
                }
            }else{
                return $content->toArray();
            }
        }
    }

    // 主表附件关联设置
    public static function setMainImageWith($imgKey,$default = ['tag']): array
    {
        $tmpWith =  [
            $imgKey => function($q){
                $q->field('id,name,url,type');
            }
        ];
        return array_merge($default,$tmpWith);
    }

    // 查询条件
    public static function setPageWhere($param): array
    {
        $where = [
            'seller_id'=>$param['sellerId'],
            'status' => 1,
            'is_del'=>1,
        ];
        if($param['isTop'] != 2){
            $where['is_top'] = 1;
        }
        if($param['isCommend'] != 2){
            $where['is_commend'] = 1;
        }
        return $where;
    }

    // 排序规则
    public static function setOrder($sort):string
    {
        $defaultOrder = "is_top desc,top_time desc";
        return $sort.',' . $defaultOrder ;
    }

    /**
     *  置顶
     * @throws ModelException
     */
    public function topOpt($param): \think\response\Json
    {
        $SubContent = new SubContent();
        $where = [
            'id' => $param['id'],
            'seller_id' => $param['seller_id']
        ];
        $data = [
            'is_top' => $param['is_top'],
            'top_time' => time()
        ];
         $res = $SubContent->updateSubContent($where,$data);
         return json($res);
    }

    /**
     * 推荐
     * @throws ModelException
     */
    public function recommendAndStatus($param): \think\response\Json
    {
        $SubContent = new SubContent();
        $where = [
            'id' => $param['id'],
            'seller_id' => $param['seller_id']
        ];
        if($param['type'] == 'recommend'){
            $data = [
                'is_recommend' => $param['is_recommend']
            ];
        }else{
            $data = [
                'status' => $param['status']
            ];
        }
        $res = $SubContent->updateSubContent($where,$data);
        return json($res);
    }

    /**
     * 副表内容
     * @throws ModelException
     * @throws ModelEmptyException
     * @throws \think\db\exception\DbException
     */
    public function mainContent($param): \think\response\Json
    {
        $moduleModel = new Module();
        $module = $moduleModel->getModule(['id'=>$param['module_id'],'seller_id'=> $param['seller_id']],['moduleField'])['data']->toArray();
        $table = $module['table'];
        self::setModel($table);
        $Category = new Category();
        $cateWhere = [
            'seller_id' => $param['seller_id'],
            'module_id' => $param['module_id'],
            'website_id' => $param['website_id'],
        ];
        $cateIds= $Category->getColumn($cateWhere)['data'];
        $subCate = new CategorySubContent();
        $field = [];
        foreach($module['moduleField'] as $val){
            if(!empty($val['settings']['relation']) && $val['settings']['relation'] == 'belongs_to_many'){
                continue;
            }else{
                array_push($field,$val['table_field']);
            }
        }
        array_unshift($field,'id');
        $subIds =  $subCate->whereIn('category_id',$cateIds)->column('sub_content_id');

        $mainContent = self::$model->field($field)->whereIn('sub_id',$subIds)->paginate($param['limit'])->each(function($item)use($module){
            $attachField = $this->setSpecialField($module['moduleField']);
            self::getSpecialField($item,$attachField);
        });
        return json(['code' => 0, 'msg' => 'ok', 'count' => $mainContent->total(), 'data' => $mainContent->all()]);
    }

    /**
     * 内容新增
     * @throws \app\exception\ModelEmptyException
     * @throws \app\exception\ModelException
     */
    public function createContent($param): \think\response\Json
    {
        $sortField = $this->getContentField($param);
        return jsonReturn(0,'success',$sortField);
    }

    /**
     * 内容新增保存
     * @throws \app\exception\ModelEmptyException
     * @throws \app\exception\ModelException
     */
    public function saveContent($param): \think\response\Json
    {
        $moduleModel = new Module();
        $module = $moduleModel->getModule(['id'=>$param['module_id'],'seller_id'=> $param['admin']['seller_id']],['moduleField','category'])['data']->toArray();
        $table = $module['table'];
        $cateFlag = $this->verifiedCate($module,$param['category_id']);
        if($cateFlag['code'] != 0){
            return json($cateFlag);
        }
        self::setModel($table);
        // 主表添加记录
        // 生成字段规则验证
        $mainData = $this->setMainContentData($module['id'],$param);

        Db::startTrans();
        try {
            // 主表记录添加结束
            $content = self::$model->create($mainData);
            $mainId = $content -> id;
            if(!empty($this->macro)){
                foreach ($this->macro as $macro){
                    if(is_string($mainData[uncamelize($macro)])){
                        $tmpData = explode(',',$mainData[uncamelize($macro)]);
                    }else{
                        $tmpData = $mainData[uncamelize($macro)];
                    }
                    $content->$macro()->attach($tmpData);
                }
            }
            // 附表添加记录
            $subContent = new SubContent();
            $subData = $this->getSubData($param,$mainId);
            $subData['module_id'] = $param['module_id'];
            $subRes = $subContent->create($subData);
            $sub_id = $subRes->id;
            // 关联分类
            $subRes->category()->attach($cateFlag['data'],['seller_id'=>$param['admin']['seller_id']]);
            // 关联标签
            if(!empty($subData['tag'])){
                if(is_string($subData['tag'])){
                    $tag = explode(',',$subData['tag']);
                }else{
                    $tag = $subData['tag'];
                }
                $subRes->tag()->attach($tag,['seller_id'=>$param['admin']['seller_id']]);
            }
            // 主表更新记录，添加附表主键
            $content->sub_id = $sub_id;
            $content->save();
            // 操作日志
            optEventLog($sub_id,'栏目内容','添加');
            Db::commit();
        }catch(\Exception $e){
            Db::rollback();
            return jsonReturn(50012,$e->getMessage());
        }
        return jsonReturn(0,'保存成功',$content);
    }

    /**
     * 内容列表
     * @param $param
     * @return \think\response\Json
     * @throws ModelException
     * @throws \think\db\exception\DbException
     */
    public function indexContent($param): \think\response\Json
    {
        $Cate = new Category();
        $cate = $Cate->getCategoryList(['seller_id'=>$param['seller_id'],'website_id'=>$param['website_id'],'lang'=>$param['lang']])['data']->toArray();
        if(empty($cate)){
            return json(['code' => 0, 'msg' => 'ok', 'count' => 0, 'data' => []]);
        }
        $cateIds = array_column($cate,'id');
        $cateSub = new CategorySubContent();
        if(empty($param['category_ids'])){
            $cateSubWhere = [
                ['seller_id','=',$param['seller_id']],
                ['category_id','in',$cateIds]
            ];
        }else{
            $param['category_ids'] = array_intersect($param['category_ids'],$cateIds);
            $cateSubWhere = [
                ['seller_id','=',$param['seller_id']],
                ['category_id','in',$param['category_ids']]
            ];
        }
        $cateSubCon = $cateSub->getAllCategorySubContent($cateSubWhere)['data'];
        if(empty($cateSubCon)){
            return json(['code' => 0, 'msg' => 'ok', 'count' => 0, 'data' => []]);
        }else{
            $subIds = array_column($cateSubCon,'sub_content_id');
            $SubContent = new SubContent();
            $content = $SubContent->with(['thumbnail'=>function($q){
                $q->field('id,name,url,type');
            },'cover'=>function($q){
                $q->field('id,name,url,type');
            }])->where(['seller_id'=>$param['seller_id'],'is_del'=>1])
                ->whereIn('id',$subIds)
                ->order('sort','asc')
                ->order('create_time','desc')
                ->paginate($param['limit']);
            return json(['code' => 0, 'msg' => 'ok', 'count' => $content->total(), 'data' => $content->all()]);
        }
    }

    // 上一篇
    public function getPreContent($param)
    {
        $cate = $param['cate'];
        $table = $cate['module']['table'];
        self::setModel($table);
        try {
            $SubContent = new SubContent();
            $cateSub = new CategorySubContent();
            $cateSubCon = $cateSub->getAllCategorySubContent(['category_id'=>$cate['id']])['data'];
            $subIds = array_column($cateSubCon,'sub_content_id');

            $where = [
                ['id','<',$param['id']],
                ['id','in',$subIds],
                ['seller_id','=',$param['seller_id']],
                ['status','=',1],
                ['is_del','=',1],
            ];
            $subContent = $SubContent->with(['thumbnail'=>function($q){
                $q->field('id,name,url,type');
            },'cover'=>function($q){
                $q->field('id,name,url,type');
            }])->where($where)->whereTime('publish_time','<',time())->order('id asc')->find();
        }catch (ModelEmptyException $me){
            throw new ModelEmptyException();
        } catch (\Exception $e){
            throw new ModelException();
        }
        return $subContent;
    }

    // 下一篇
    public function getNextContent($param)
    {
        $cate = $param['cate'];
        $table = $cate['module']['table'];
        self::setModel($table);
        try {
            $SubContent = new SubContent();
            $cateSub = new CategorySubContent();
            $cateSubCon = $cateSub->getAllCategorySubContent(['category_id'=>$cate['id']])['data'];
            $subIds = array_column($cateSubCon,'sub_content_id');
            $where = [
                ['id','>',$param['id']],
                ['id','in',$subIds],
                ['seller_id','=',$param['seller_id']],
                ['status','=',1],
                ['is_del','=',1],
            ];
            $subContent = $SubContent->with(['thumbnail'=>function($q){
                $q->field('id,name,url,type');
            },'cover'=>function($q){
                $q->field('id,name,url,type');
            }])->where($where)->whereTime('publish_time','<',time())->order('id asc')->find();
        }catch (ModelEmptyException $me){
            throw new ModelEmptyException();
        } catch (\Exception $e){
            throw new ModelException();
        }
        return $subContent;
    }

    /**
     * 前台详情
     * @param $param
     * @return mixed
     * @throws ModelEmptyException
     * @throws ModelException
     */
    public function getContentDetail($param)
    {
        $cate = $param['cate'];
        $table = $cate['module']['table'];
        self::setModel($table);
        try {
            $SubContent = new SubContent();
            $where = [
                ['id','=',$param['id']],
                ['seller_id','=',$param['seller_id']],
                ['publish_time','<',date('Y-m-d H:i:s',time())],
                ['status','=',1],
                ['is_del','=',1],
            ];
            $subContent = $SubContent->getSubContent($where,['thumbnail'=>function($q){
                $q->field('id,name,url,type');
            },'cover'=>function($q){
                $q->field('id,name,url,type');
            }])['data'];
            $article = self::$model->where(['sub_id' => $param['id'], 'seller_id' => $param['seller_id']])->find();
            if(empty($article)){
                throw new ModelEmptyException();
            }
            $attachField = $this->setSpecialField($cate['module']['moduleField']);

            $this->getSpecialField($article,$attachField);
            $subContent['main_content'] = $article;



        }catch (ModelEmptyException $me){
            throw new ModelEmptyException();
        } catch (\Exception $e){
            throw new ModelException();
        }
        return $subContent;
    }


    /**
     * 内容详情
     * @throws \app\exception\ModelEmptyException
     * @throws ModelException
     */
    public function readContent($param): \think\response\Json
    {
        $moduleModel = new Module();
        $module = $moduleModel->getModule(['id'=>$param['module_id'],'seller_id'=> $param['seller_id']],['moduleField'])['data']->toArray();
        $table = $module['table'];
        self::setModel($table);
        try {
            $SubContent = new SubContent();
            $subContent = $SubContent->getSubContent(['id'=>$param['id'],'seller_id'=>$param['seller_id'],'is_del'=>1],['thumbnail'=>function($q){
                $q->field('id,name,url,type');
            },'cover'=>function($q){
                $q->field('id,name,url,type');
            },'category','tag'=>function($query)use($param){
                $query->where(['website_id'=>$param['website_id'],'lang'=>$param['lang']]);
            }])['data']->toArray();
            $article = self::$model->where(['sub_id' => $param['id'], 'seller_id' => $param['seller_id']])->find();

             if(empty($article)){
                throw new ModelEmptyException();
            }

             $cate = $subContent['category'];
            if(!empty($cate)){
                $cateIds = array_column($cate,'id');
                $subContent['category'] = $cateIds;
                $siteIds = array_values(array_unique(array_column($cate,'website_id')));
                $subContent['website'] = $siteIds;
            }
             $tag = $subContent['tag'];
             if(!empty($tag)){
                 $tagIds = array_column($tag,'id');
                 $subContent['tag'] = $tagIds;
             }
             $attachField = $this->setSpecialField($module['moduleField']);
             $this->getSpecialField($article,$attachField);

             $subContent['main_content'] = $article;
         }catch (ModelEmptyException $me){
             throw new ModelEmptyException();
         } catch (\Exception $e){
             throw new ModelException();
         }
        $contentField = $this->getContentField($param);
        return jsonReturn(0,'success',[
            'field' => $contentField,
            'content' => $subContent
        ]);
    }

    /**
     * 获取附件字段
     * @param $moduleField
     * @return array[]
     */
    public static function getAttachField($moduleField): array
    {
        return self::setSpecialField($moduleField);
    }

    /**
     * @param $article
     * @param $attachField
     * @return mixed
     */
    public static function getMainContent($article, $attachField)
    {
        self::getSpecialField($article,$attachField);
        return $article;
    }

    public static function getSpecialField(&$article,$attachField)
    {
        self::getAttachPath($article,$attachField);
        if(!empty(self::$belongsTo)){
            foreach(self::$belongsTo as $belong){
                $article[$belong['foreign_key']] = self::getHasOneData($belong['table'],$belong['local_key'],$article[$belong['foreign_key']]);
            }
        }
        if(!empty(self::$hasMany)){
            foreach(self::$hasMany as $hasMany){
                $article[$hasMany['foreign_key']] = self::getHasManyData($hasMany['table'],$hasMany['local_key'],$article[$hasMany['foreign_key']]);
            }
        }
        if(!empty(self::$macro)){
            foreach(self::$macro as $macro){
                $article[uncamelize($macro)] = $article->$macro()->select();
            }
        }
    }

    /**
     * 内容删除
     * @param $param
     * @return \think\response\Json
     */
    public function deleteContent($param): \think\response\Json
    {
        $module = $this->getModule($param['module_id'], $param['seller_id']);
        $table = $module['table'];
        self::setModel($table);
        Db::startTrans();
        try{
            $SubContent = new SubContent();
            $subContent = $SubContent->where(['id'=>$param['id'],'seller_id'=>$param['seller_id'],'is_del'=>1])->find();
            if(empty($subContent)){
                return jsonReturn(0,'删除成功',$subContent);
            }
            // 主表软删
            $subContent->is_del = 2;
            $subContent->delete_time = time();
            $subContent->update_time = time();
            $subContent->save();
            // 副表软删
            $content = self::$model->where(['sub_id'=>$param['id'],'seller_id'=>$param['seller_id']])->find();
            if(!empty($content)){
                $content->is_del = 2;
                $content->delete_time = time();
                $content->update_time = time();
                $content->save();
            }

            // 复制删除内容到回收站表
            $recycleBin = new RecycleBin();
            $binData = [
                'seller_id' => $param['seller_id'],
                'object_id' => $content ? $content['id'] : 0,
                'sub_id' => $subContent['id'],
                'module_id' => $param['module_id'],
                'table_name' => $module['table'],
                'title' => !empty($content['title']) ? $content['title'] : $module['title'].'内容',
                'admin_id' => $param['admin_id'],
                'name' => $param['name'],
            ];
            $recycleBin -> addRecycleBin($binData);
            // 操作日志
            optEventLog($subContent['id'],'栏目内容','删除');
            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            return jsonReturn(50025,$e->getMessage());
        }
        return jsonReturn(0,'删除成功',$content);
    }

    /**
     * 更新内容
     * @throws ModelException
     * @throws ModelEmptyException
     */
    public function updateContent(&$param): \think\response\Json
    {
        $module = $this->getModule($param['module_id'], $param['admin']['seller_id']);
        $table = $module['table'];
        self::setModel($table);
        $cateFlag = $this->verifiedCate($module,$param['category_id']);
        if($cateFlag['code'] != 0){
            return json($cateFlag);
        }
        $content = self::$model->with('subContent.category')->where(['sub_id'=>$param['id'],'seller_id'=>$param['admin']['seller_id']])->find();
        if(empty($content)){
            return jsonReturn(40004,'内容不存在');
        }
        $subContent = $content['subContent'];
        // 主表添加记录
        // 生成字段规则验证
        $param['main_id'] = $content['id'];
        $mainData = $this->setMainContentData($module['id'],$param,true);
        Db::startTrans();
        try {
            // 主表更新内容
            $res = $content->saveAll([$mainData]);
            $mainId = $content -> id;
            if(!empty($this->macro)){
                foreach ($this->macro as $macro){
                    $content->$macro()->detach();
                    if(is_string($mainData[uncamelize($macro)])){
                        $tempData = explode(',',$mainData[uncamelize($macro)]);
                    }else{
                        $tempData = $mainData[uncamelize($macro)];
                    }
                    $content->$macro()->attach($tempData);
                }
            }
            // 附表添加记录
            $param['sub_id'] = $content['subContent']['id'];
            $subData = $this->getSubData($param,$mainId,true);
            $subContent->saveAll([$subData]);
            $subContent->category()->detach();
            $subContent->category()->attach($cateFlag['data'],['seller_id'=>$param['admin']['seller_id']]);
            // 关联标签
            if(is_string($subData['tag'])){
                $tag = explode(',',$subData['tag']);
            }else{
                $tag = $subData['tag'];
            }
            $subContent->tag()->detach();
            $subContent->tag()->attach($tag,['seller_id'=>$param['admin']['seller_id']]);
            // 操作日志
            optEventLog($param['sub_id'],'栏目内容','更新');
            Db::commit();
        }catch(\Exception $e){
            Db::rollback();
            return jsonReturn(50012,$e->getMessage());
        }
        return jsonReturn(0,'保存成功',$res);

    }

    /**
     * 设置主表内容
     * @param $moduleId
     * @param $param
     * @param false $isEdit
     * @return mixed|\think\response\Json
     * @throws ModelException
     * @throws \Exception
     */
    public function setMainContentData($moduleId, $param, bool $isEdit = false)
    {
        $moduleField = new ModuleField();
        $field = $moduleField->getModuleFieldList(['module_id'=>$moduleId,'seller_id'=>$param['admin']['seller_id']])['data']->toArray();
        $rule = [];
        $arrayFieldKey=[];
        foreach ($field as $val){
            if(!empty($val['validate_rule'])){
                $rule_key = $val['table_field'] .'|'. $val['form_title'];
                $rule[$rule_key] = $val['validate_rule'];
            }
            if(in_array($val['type'],self::$arrayField)){
                $rule_key = $val['table_field'] .'|'. $val['form_title'];
                $rule[$rule_key] = 'array';
                array_push($arrayFieldKey,$val['table_field']);
            }
            if($val['type'] == '关联字段' && $val['settings']['relation'] == 'belongs_to_many'){
                $func = camelize($val['table_field']);
                $middle = $val['settings']['local_table'] . '_' . $val['settings']['table'];
                $this->setRelation($func,$val['settings']['table'],$middle);
            }
            if($val['type'] == '关联字段' && ($val['settings']['relation'] == 'has_many' || $val['settings']['relation'] == 'belongs_to_many')){
                array_push($arrayFieldKey,$val['table_field']);
            }
        }

        // 验证数据
        if(!empty($rule)){
            try{
                validate($rule)->check($param['main_content']);
            }catch (ValidateException $e){
                throw new \Exception($e->getError(),-422);
            }
        }
        $mainData = $param['main_content'];
        foreach($mainData as $mainKey => $main){
            if(in_array($mainKey,$arrayFieldKey) && !empty($main)){
                $mainData[$mainKey] = json_encode($main);
            }
        }
        
        $mainData['seller_id'] = $param['admin']['seller_id'];
        if($isEdit){
            $mainData['id'] = $param['main_id'];
        }
        return $mainData;
    }

    /**
     * 验证分类
     * @param $module
     * @param $categoryIds
     * @return array
     */
    public function verifiedCate($module,$categoryIds): array
    {
        if(empty($module['category'])){
            $cateIds = [];
        }else{
            $cateIds = array_column($module['category'],'id');
            $cateFlag = array_diff($categoryIds,$cateIds);
        }
        if(empty($cateIds) || !empty($cateFlag)){
            return dataReturn(50029,'有栏目数据不属于该模型，请重新选择');
        }
        return dataReturn(0,'success',$categoryIds);
    }

    /**
     * 获取特殊字段（附件+关联关系字段+数组格式转换字段）
     * @param $param
     * @return array
     */
    public static function setSpecialField($param): array
    {
        // 单附件
        $singleField = [];
        // 多附件
        $multiField = [];
        // 格式转化字段
        $arrField = [];

        foreach($param as $item){
            if(in_array($item['form_type'],['image','video','file'])){
                array_push($singleField,$item['table_field']);
            }
            if(in_array($item['form_type'],['multiImage','multiVideo','multiFile'])){
                array_push($multiField,$item['table_field']);
            }
            if($item['form_type'] == 'reference'){
                if($item['settings']['relation'] == 'belongs_to'){
                    $func = camelize($item['table_field']);
                    $tmp = [
                        // 关联方法
                        'func_name' => $func,
                        'table' => $item['settings']['table'],
                        'local_key' => $item['settings']['local_key'],
                        'foreign_key' => $item['settings']['foreign_key'],
                    ];
                    self::$belongsTo[$item['table_field']] = $tmp;
                }

                if($item['settings']['relation'] == 'has_many'){
                    $tmp = [
                        // 关联方法
                        'func_name' => camelize($item['table_field']),
                        'table' => $item['settings']['table'],
                        'local_key' => $item['settings']['local_key'],
                        'foreign_key' => $item['settings']['foreign_key'],
                    ];
                    self::$hasMany[$item['table_field']] = $tmp;
                }
                if($item['settings']['relation'] == 'belongs_to_many'){
                    $middle = $item['settings']['local_table'] . '_' . $item['settings']['table'];
                    self::setRelation(camelize($item['table_field']),$item['settings']['table'],$middle);
                }
            }
            if(in_array($item['form_type'],['dateTimeRange','multiSelect','checkbox'])){
                array_push($arrField,$item['table_field']);
            }
        }
        return [
            'single' => $singleField,
            'multi' => $multiField,
            'arrField' => $arrField,
        ];
    }

    /**
     * 获取附件链接
     */
    public static function getAttachPath($item, $attachField)
    {
        $attachment = new Attachment();
        // 单附件
        if(count($attachField['single'])){
            $singleIds = [];
            $singleField = [];
            foreach($attachField['single'] as $val){
//                if($item[$val]){
                    array_push($singleIds,$item[$val]);
                    $singleField[$val] = $item[$val];
//                }
            }
            $singleAttach = $attachment->field('id,name,url,type')->whereIn('id',$singleIds)->select()->toArray();
            $singleAttach = getColumnForKeyArray($singleAttach,'id');
            if(!empty($singleAttach)){
                foreach ($singleField as $kk => $vv){
                    if($vv == 0 || !isset($singleAttach[$vv])){
                        $item[$kk] = null;
                    }else{
                        $item[$kk] = $singleAttach[$vv];
                    }
                }
            }

        }

        // 多附件
        if(count($attachField['multi'])){
            $idStr = [];
            $multiFields = [];
            foreach($attachField['multi'] as $multi){
                if($item[$multi]){
                    $idArr = json_decode($item[$multi],true);
                    $multiFields[$multi] = $idArr;
                    $idStr = array_merge($idStr,$idArr);
                }else{
                    $item[$multi] = [];
                }
            }
            if(!empty($idStr)){
                $multiIds = array_unique($idStr);
                $multiAttach = $attachment -> field('id,name,url,type')->whereIn('id',$multiIds)->select()->toArray();

                $multiAttach = getColumnForKeyArray($multiAttach,'id');
                foreach($multiFields as $km => $vm){
                    $attachments = [];
                    if(!empty($multiAttach)){
                        foreach ($vm as $vvm) {
                            if(isset($multiAttach[intval($vvm)])){
                                array_push($attachments,$multiAttach[intval($vvm)]);
                            }
                        }
                    }
                    $item[$km] = $attachments;
                }
            }
        }
        // 数组转化字段
        if(count($attachField['arrField'])){
            foreach($attachField['arrField'] as $ak => $ar){
                if(!empty($ar)){
                    if(empty($item[$ar])){
                        $item[$ar] = [];
                    }else{
                        $item[$ar] = json_decode($item[$ar],true);
                    }
                }
            }
        }
    }

    /**
     * 获取一对一关联数据
     * @param $relationTable
     * @param $key
     * @param $val
     * @param string $field
     * @param int $sellerId
     * @return mixed
     */
    public static function getHasOneData($relationTable, $key, $val, string $field = '*', int $sellerId = 1)
    {
        $model = self::getRelationModel($relationTable);
        return $model->field($field)->where($key,$val)->where('seller_id',$sellerId)->find();
    }

    /**
     * 获取多对多关联数据
     * @param $relationTable
     * @param $key
     * @param $val
     * @param string $field
     * @param int $sellerId
     * @return mixed
     */
    public static function getHasManyData($relationTable, $key, $val, string $field = '*', int $sellerId = 1)
    {
        $model = self::getRelationModel($relationTable);
        $tmpData = [];
        if($val){
            $tmpData = json_decode($val,true);
        }
        return $model->field($field)->whereIn($key,$tmpData)->where('seller_id',$sellerId)->select();
    }

    public static function getRelationModel($relationTable)
    {
        $modelName = '\\app\\model\\' . ucfirst(camelize($relationTable));
        return new $modelName();
    }

    /**
     * 设置模型关联关系
     * @param Model $model
     * @param array $assocField
     */
    public static function setRelation($func,$table,$middle)
    {
        array_push(self::$macro,$func);
        $closure = function ()use($table,$middle){
            return $this->belongsToMany(ucfirst(camelize($table)),$middle);
        };
        self::$model->macro($func,$closure);
    }

    /**
     * 获取字段值和注释
     *
     * @param string $table
     * @return array
     */
    public function getTableField(string $table): array
    {
        return $this->table->getTableField($table);
    }

    /**
     * 获取内容展示字段
     * @throws ModelException
     * @throws \app\exception\ModelEmptyException
     */
    public function getContentField($param): array
    {
        $module = self::getModule($param['module_id'],$param['seller_id']);
        $sort_field = [];
        $field = $this->getTableField($module['database_table']);
        // 自定义模型
        // 处理数组顺序,按照数据表字段排序，确定表单顺序
        $form_field = $module['moduleField'];
        foreach($form_field as $val){
            foreach($field as $k => $v){
                if(isset($v['column_name'])){
                    if($val['table_field'] == $v['column_name']){
                        $sort_field[$k] = $val;
                    }
                }else{
                    if($val['table_field'] == $v['COLUMN_NAME']){
                        $sort_field[$k] = $val;
                    }
                }
            }
        }

        ksort($sort_field);

        return $sort_field;
    }

    /**
     * @throws ModelEmptyException
     * @throws ModelException
     */
    public  static function getModule($module_id,$seller_id)
    {
        $moduleModel = new Module();
        return $moduleModel->getModule(['id'=>$module_id,'seller_id'=> $seller_id],['moduleField','category'])['data']->toArray();
    }

    /**
     * 获取分类
     * @throws \app\exception\ModelEmptyException
     * @throws ModelException
     */
    public static function getCate($param)
    {
        $category = new Category();
        return $category->getCategory($param,['module.moduleField'])['data']->toArray();
    }

    /**
     * 设置模型
     * @param string $table
     */
    public static function setModel(string $table)
    {
        $model = ucfirst(camelize($table));
        $class = 'app\\model\\'.$model;
        return self::$model = new $class();
    }

    /**
     * 组装附表数据
     * @param $param
     * @param $mainId
     * @return mixed
     */
    public function getSubData($param, $mainId, $isEdit = false)
    {
        $subData = $param['sub_content'];
        $subData['main_id'] = $mainId;
        $subData['seller_id'] = $param['admin']['seller_id'];
        $subData['admin_id'] = $param['admin']['uid'];
        if(empty($subData['author'])){
            $subData['author'] = $param['admin']['name'];
        }
        if($isEdit){
            $subData['id'] = $param['sub_id'];
        }
        if(empty($subData['tag'])){
            $subData['tag'] = '';
        }
        return $subData;
    }
}